#if !defined(_COMMAND_H)
#define _COMMAND_H

#include "CommandDescriptor.h"
#include "SStruct.h"
#include "Utility.h"

CREATE_ALIAS( Command )
CREATE_MAP_ALIAS( Command )

/**
 * Class use to store information about a command.
 */
class DECLARATION_DLL Command
{
	/** The command descriptor. */
    CommandDescriptorSp cmd;

	/** Struct used to store the inputs variables of the command. */
	SStructSp inputs;

	/** Struct used to store the outputs variables of the command. */
    SStructSp outputs;

	/**
	 * Create a Command object.
	 */
	Command(CommandDescriptorSp cd, SStructSp inputs, SStructSp outputs)
	{
		this->cmd = cd;
		this->inputs = inputs;
		this->outputs = outputs;
	}

public:

	/**
 	 *	Get the command name.
	 */ 
	virtual string GetCommandName()
	{
		return cmd->GetName();
	}

	/**
	 *	Get the command descriptor.
	 */ 
	virtual CommandDescriptorSp GetCommandDescriptor()
	{
		return cmd;
	}

	/**
	 * Returns the number of input parameter of the command.
	 */
	virtual int GetNumberOfInputs()
	{
		return inputs->GetTypeDescriptor()->As<SStructTypeDescriptor>()->GetNumberOfMembers();
	}

	/**
	* Returns the number of output parameter of the command.
	*/
	virtual int GetNumberOfOutputs()
	{
		return outputs->GetTypeDescriptor()->As<SStructTypeDescriptor>()->GetNumberOfMembers();
	}

	/**
 	 *	Get the inputs struct type descriptor.
	 */ 
	virtual SStructTypeDescriptorSp GetInputsTypeDescriptor()
	{
		return inputs->GetTypeDescriptor()->As<SStructTypeDescriptor>();
	}

	/**
	*	Get the outputs struct type descriptor
	*/ 
	virtual SStructTypeDescriptorSp GetOutputsTypeDescriptor()
	{
		return outputs->GetTypeDescriptor()->As<SStructTypeDescriptor>();
	}

	/**
	*	Get the input variables as a struct.
	*/ 
	virtual SStructSp GetInputs()
	{
		return inputs;
	}

	/**
	*	Get the outputs variables as a struct.
	*/ 
	virtual SStructSp GetOutputs()
	{
		return outputs;
	}

	/**
	 * Get the type descriptor of an input parameter by index.
	 */
	template <typename T>
	shared_ptr<T> GetInputTypeDescriptor(int index)
	{
		return cmd->GetInputParameter(index)->GetTypeDescriptor()->As<T>();
	}

	/**
	 * Get the type descriptor of an input parameter by key.
	 */
	template <typename T>
	shared_ptr<T> GetInputTypeDescriptor(string parameterName)
	{
		return cmd->GetInputParameter(parameterName)->GetTypeDescriptor()->As<T>();
	}

	/**
	 * Get the type descriptor of an output parameter by index.
	 */
	template <typename T>
	shared_ptr<T> GetOutputTypeDescriptor(int index)
	{
		return cmd->GetOutputParameter(index)->GetTypeDescriptor()->As<T>();
	}

	/**
	 * Get the type descriptor of an output parameter by key.
	 */
	template <typename T>
	shared_ptr<T> GetOutputTypeDescriptor(string parameterName)
	{
		return cmd->GetOutputParameter(parameterName)->GetTypeDescriptor()->As<T>();
	}

	/**
	 * Factory method to create a command (no use of variables in the commandArgs).
	 */
	static CommandSp Create(CommandDescriptorSp cd, string commandArgs);

	/**
	 * Factory method to create a command (use of implicit variables in the commandArgs).
	 */
	static CommandSp Create(CommandDescriptorSp cd, string commandArgs, SValueSpMapSp implicitArgs);

	/**
	 * Factory method to create a command (use of variables or implicit variables in the commandArgs).
	 */
	static CommandSp Create(CommandDescriptorSp cd, string commandArgs, SValueSpMapSp implicitArgs, SValueSpMapSp vars);

};

#endif  //_COMMAND_H
